#include "common.h"
#include "log4z.h"

//获取当前时间毫秒
unsigned int TimGetTicks()
{
#ifdef WIN32
	return timeGetTime();
#else
	struct timeval tv;
	gettimeofday(&tv, NULL);
	return (tv.tv_sec * 1000 + tv.tv_usec / 1000);
#endif
}

static char* utils_inet_ntoa(struct sockaddr_storage in) {
	static char string[INET6_ADDRSTRLEN];
	void* in_ptr;

	if (in.ss_family == AF_INET) {
		in_ptr = &((struct sockaddr_in*)&in)->sin_addr;
	}
	else if (in.ss_family == AF_INET6) {
		in_ptr = &((struct sockaddr_in6*)&in)->sin6_addr;
	}
	else {
		// 不支持的地址族
		LOGFMTE("不支持的地址族: %d", in.ss_family);
		string[0] = '\0';
		return string;
	}

	if (inet_ntop(in.ss_family, in_ptr, string, INET6_ADDRSTRLEN) == NULL) {
		LOGFMTE("inet_ntop() 失败: %s", strerror(errno));
		string[0] = '\0';
	}

	return string;
}

static int utils_ntohs(struct sockaddr_storage in) {
	return ntohs(((struct sockaddr_in*)&in)->sin_port);
}

const std::string get_ip_prot(int fd)
{
	// struct sockaddr_storage peerAddr = get_sockaddr_storage(fd);
	struct sockaddr_storage peerAddr;
#ifdef _WIN32
	int peerLen = sizeof(peerAddr);
#else
	unsigned int peerLen = sizeof(peerAddr);
#endif
	getpeername(fd, (struct sockaddr*)&peerAddr, &peerLen);
	std::string rt = utils_inet_ntoa(peerAddr);
	rt.append(":");
	rt.append(std::to_string(utils_ntohs(peerAddr)));
	return rt;
}

//LPCWSTR ConvertCharToLPCWSTR(const char* inputString) {
//	int inputStringLength = strlen(inputString) + 1; // Include null terminator
//
//	// Convert char* to wchar_t*
//	int bufferSize = MultiByteToWideChar(CP_UTF8, 0, inputString, inputStringLength, NULL, 0);
//	wchar_t* wideString = new wchar_t[bufferSize];
//	MultiByteToWideChar(CP_UTF8, 0, inputString, inputStringLength, wideString, bufferSize);
//
//	// Use wideString as LPCWSTR
//	LPCWSTR lpcwStr = wideString;
//
//	// Clean up
//	delete[] wideString;
//
//	return lpcwStr;
//}

//std::string ConvertWCHARToString(const WCHAR* wideString) {
//	// Get the length of the wide string
//	int length = wcslen(wideString);
//
//	// Allocate a buffer for the converted string
//	char* buffer = new char[length + 1];
//
//	// Convert wide string to multibyte string
//	WideCharToMultiByte(CP_UTF8, 0, wideString, -1, buffer, length + 1, NULL, NULL);
//
//	// Create a std::string from the converted string
//	std::string result(buffer);
//
//	// Clean up
//	delete[] buffer;
//
//	return result;
//}

std::string ExtractIconName(const std::string& cssClassName) {
	size_t startPos = cssClassName.find('.');
	if (startPos != std::string::npos) {  // Check if '.' is found
		return cssClassName.substr(startPos + 1);
	}
	else {
		LOGFMTE("Error: '.' not found in the string");
		return "";  // Return an empty string on error
	}
}


//LPCWSTR CharToLPCWSTR(const char* charString) {
//	// 计算需要的缓冲区大小
//	int size = MultiByteToWideChar(CP_UTF8, 0, charString, -1, NULL, 0);
//
//	// 分配缓冲区
//	wchar_t* wideString = new wchar_t[size];
//
//	// 进行转换
//	MultiByteToWideChar(CP_UTF8, 0, charString, -1, wideString, size);
//
//	// 返回宽字符字符串
//	return wideString;
//}

//std::string WCHARToString(const WCHAR* wideString) {
//	// 获取宽字符字符串的长度
//	int wideLength = wcslen(wideString);
//
//	// 计算需要的缓冲区大小（不包括结尾的空字符）
//	int bufferSize = WideCharToMultiByte(CP_UTF8, 0, wideString, wideLength, nullptr, 0, nullptr, nullptr);
//
//	// 分配缓冲区
//	char* buffer = new char[bufferSize + 1];  // 加一用于存放结尾的空字符
//
//	// 进行转换
//	WideCharToMultiByte(CP_UTF8, 0, wideString, wideLength, buffer, bufferSize, nullptr, nullptr);
//
//	// 添加结尾的空字符
//	buffer[bufferSize] = '\0';
//
//	// 将转换后的字符串存入 std::string 中
//	std::string result(buffer);
//
//	// 释放动态分配的内存
//	delete[] buffer;
//
//	return result;
//}

char* GetExeFilePaths(char* sFilePath, const char* sFileName)
{
#ifdef _WIN32
	wchar_t wideFilePath[MAX_PATH];
	GetModuleFileNameW(nullptr, wideFilePath, MAX_PATH);

	char narrowFilePath[MAX_PATH];
	WideCharToMultiByte(CP_UTF8, 0, wideFilePath, -1, narrowFilePath, MAX_PATH, nullptr, nullptr);

	char* lastBackslash = strrchr(narrowFilePath, '\\');
	if (lastBackslash != nullptr) {
		*(lastBackslash + 1) = '\0'; // Include the backslash in the path
	}
	strcpy(sFilePath, narrowFilePath);
#else
	if (getcwd(sFilePath, PATH_MAX) == nullptr) {
		LOGFMTE("Get path fail!");
		return nullptr;
	}
	strcat(sFilePath, "/");
#endif

	return strcat(sFilePath, sFileName);
}

#ifdef WIN32
int GetFilePaths(const std::string& directory, std::map<std::string, std::string>& allFiles) {
	std::string dir2 = directory + "\\*.*";

	intptr_t handle;
	_finddata_t findData;

	handle = _findfirst(dir2.c_str(), &findData);
	if (handle == -1) {
		LOGFMTE("Can not find the file ... ");
		return handle;
	}

	do {
		if (findData.attrib & _A_SUBDIR) { // Check if it's a subdirectory
			// Ignore "." and ".." directories
			if (strcmp(findData.name, ".") == 0 || strcmp(findData.name, "..") == 0)
				continue;

			// Append "\\" and the subdirectory name for the next search
			std::string dirNew = directory + "\\" + findData.name;
			std::map<std::string, std::string> tempFiles;
			GetFilePaths(dirNew, tempFiles);
			allFiles.insert(tempFiles.begin(), tempFiles.end());
		}
		else { // Not a subdirectory, i.e., it's a file
			std::string filePath = directory + "\\" + findData.name;
			allFiles[findData.name] = filePath;
			//std::cout << findData.name << ": " << filePath << std::endl;
		}
	} while (_findnext(handle, &findData) == 0);
	_findclose(handle); // Close the search handle

	return 0;
}
#else
int GetFilePaths(const std::string& directory, std::map<std::string, std::string>& allFiles)
{
	DIR* dir = 0;
	struct stat st;
	char sFilePath[256] = { 0 };
	struct dirent* filename;
	if (0 == getcwd(sFilePath, 256)) {
		LOGFMTE("Get path fail!");
		return XX_ERR_NONE;
	}

	if (0 == directory) {
		LOGFMTE(" directory is null ! :%s", directory);
		return XX_ERR_ERROR;
	}
	lstat(directory, &st);
	if (!S_ISDIR(st.st_mode)) {
		LOGFMTE("directory is not a valid directory ! :%s", directory);
		return XX_ERR_ERROR;
	}

	if (0 == (dir = opendir(directory))) {
		LOGFMTE("Can not open dir %s", directory);
		return XX_ERR_ERROR;
	}
	/* read all the files in the dir ~ */
	while ((filename = readdir(dir)) != 0) {
		if (strcmp(filename->d_name, ".") == 0 ||
			strcmp(filename->d_name, "..") == 0) {
			continue;
		}
		snprintf(sFilePath, sizeof(sFilePath), "%s/%s", directory, filename->d_name);

		if (lstat(sFilePath, &st) == -1) {
			LOGFMTE("directory is not a valid directory ! %s", sFilePath);
			closedir(dir);
			return XX_ERR_ERROR;
		}

		if (S_ISDIR(st.st_mode)) {
			GetFilePaths(sFilePath);
			continue;
		}
		snprintf(sFilePath, sizeof(sFilePath), "%s/%s", directory, filename->d_name);
		// CAutoMutex AutoMutex(m_mutexMapFile);
		allFiles[filename->d_name] = sFilePath;
		LOGFMTI("[%s][%s]", filename->d_name, sFilePath);
	}
	closedir(dir);
	return XX_ERR_NONE;
}

#endif

bool startsWith(const std::string& str, const std::string& prefix) {
	if (str.size() < prefix.size()) {
		return false;
	}
	for (size_t i = 0; i < prefix.size(); ++i) {
		if (str[i] != prefix[i]) {
			return false;
		}
	}
	return true;
}

std::vector<std::string> split(const std::string& s, const char* delim)
{
	std::vector<std::string> ret;
	size_t last = 0;
	auto index = s.find(delim, last);
	while (index != std::string::npos) {
		if (index - last > 0) {
			ret.push_back(s.substr(last, index - last));
		}
		last = index + strlen(delim);
		index = s.find(delim, last);
	}
	if (!s.size() || s.size() - last > 0) {
		ret.push_back(s.substr(last));
	}
	return ret;
}
